package com.harveyspace.aes.social.weixin;

import com.harveyspace.aes.core.utils.HttpUtil;
import com.harveyspace.aes.core.utils.JsonUtil;
import com.harveyspace.aes.social.Oauth;
import com.harveyspace.aes.social.SocialConfig;
import com.harveyspace.aes.social.exception.SocialException;
import com.harveyspace.aes.social.pojo.AccessTokenInfo;
import com.harveyspace.aes.social.pojo.SocialiteUserInfo;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 微信第三方登录
 *
 * @Author <a href="harveyer@163.com">harvey</a>
 * @date 2018/2/9
 */
public class OauthWeixin extends Oauth {
    
	private final String TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
	private final String USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo";

	/**
     * @param socialConfig 配置信息
     */
    public OauthWeixin(SocialConfig socialConfig) {
        super(socialConfig);
    }
    
	/**
	 * 获取授权url
	 * @return String url
	 */
	@Override
    public String getAuthorizeUrl(String state) {

		Map<String, String> params = new HashMap<>();
        params.put("appid", socialConfig.getClientId());
        params.put("response_type", "code");
        params.put("redirect_uri", socialConfig.getRedirectUri());
        params.put("state", state.concat("#wechat_redirect"));

        String authUrl;

        switch (socialConfig.getType()) {
            case "mp" :
                authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize";
                params.put("scope", "snsapi_userinfo");
                break;
            case "app":
                authUrl = "";
                break;
            default:
                authUrl = "https://open.weixin.qq.com/connect/qrconnect";
                params.put("scope", "snsapi_login");
                break;
        }

		return initParams(authUrl, params);
	}
	
	/**
	 * 获取UserInfo
	 * 
	 * @param accessToken AccessToken
     * @param openId openid
	 * @return String 返回类型
	 * @throws SocialException 获取用户信息异常
	 */
	private WeiXinUserInfo getUserInfo(String accessToken, String openId) throws SocialException {

		Map<String, String> params = new HashMap<>();
		params.put("access_token", accessToken);
		params.put("openid", openId);

        String result;
        try {
            result = HttpUtil.getString(initParams(USER_INFO_URL, params), 1);
        } catch (IOException e) {
            String errorMessage = String.format("通过 accessToken[%s]，openid[%s] 获取用户信息异常", accessToken, openId);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        return JsonUtil.toObject(result, WeiXinUserInfo.class);
	}

    /**
     * 获取token 返回的是JSON 解析获取到Token以及OpenId
     * 
     * @param code 使用code换取token
     * @return String 返回类型
     * @throws SocialException 登录异常
     */
    @Override
    public AccessTokenInfo getAccessToken(String code) throws SocialException {

        Map<String, Object> params = new HashMap<>();
        params.put("code", code);
        params.put("appid", socialConfig.getClientId());
        params.put("secret", socialConfig.getClientSecret());
        params.put("grant_type", "authorization_code");

        String result;
        try {
            result = HttpUtil.postString(TOKEN_URL, 1, params);
        } catch (IOException e) {

            String errorMessage = String.format("通过 code[%s] 获取 access token异常", code);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        Map<String, Object> responseMap = JsonUtil.toMap(result);

        if(StringUtils.isNotBlank(MapUtils.getString(responseMap, "errcode"))){

            String errorCode = MapUtils.getString(responseMap, "errcode");
            String errorMessage = MapUtils.getString(responseMap, "errmsg");

            throw new SocialException(String.format("通过 code[%s] 获取 access token异常:%s[%s]", code, errorMessage, errorCode));
        }

        return JsonUtil.toObject(result, AccessTokenInfo.class);
    }

    @Override
    public SocialiteUserInfo getSocialUserInfo(AccessTokenInfo accessTokenInfo) throws SocialException {

        String accessToken = accessTokenInfo.getAccessToken();
        String openId = accessTokenInfo.getOpenId();

        if (StringUtils.isBlank(accessToken)) {
            throw new SocialException("accessToken is Blank!");
        }

        if (StringUtils.isBlank(openId)) {
            throw new SocialException("openId is Blank!");
        }

        SocialiteUserInfo socialiteUserInfo = new SocialiteUserInfo();
        socialiteUserInfo.setUnionId(accessTokenInfo.getUnionId());
        socialiteUserInfo.setOpenId(accessTokenInfo.getOpenId());

        WeiXinUserInfo info = getUserInfo(accessToken, openId);

        if(null != info) {
            socialiteUserInfo.setAvatar(info.getHeadimgurl());
            socialiteUserInfo.setNickName(info.getNickname());
            socialiteUserInfo.setName(info.getNickname());
        }

        return socialiteUserInfo;
    }
}
